package semafori;

import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;

public class SemaforoBinarioAPriorita implements SemaforoAPriorita {

	private static class Elemento implements Comparable<Elemento>{
		private Thread T;
		private int priority;
		public Elemento(Thread T, int priority){
			this.T=T;
			this.priority=priority;
		}
		public Thread getThread(){
			return T;
		}
		
		public int getPriority(){
			return priority;
		}
		
		public int compareTo(Elemento e){
			return this.priority-e.priority;
		}
		
		public String toString(){
			return T.toString()+" priority: "+priority;
		}
	}
	
	private PriorityQueue<Elemento> codaAPriorita=new PriorityQueue<Elemento>();
	private int permessi, daSvegliare = 0;
	
	public SemaforoBinarioAPriorita(int permessi) {
		if(permessi<0 || permessi>1)
			throw new IllegalArgumentException();
		
		this.permessi = permessi;
	}
	
	@Override
	public synchronized void P(int priority) {
		// TODO Auto-generated method stub
		if(permessi==0){
			codaAPriorita.add(new Elemento(Thread.currentThread(), priority));
			while(true){
				try{
					wait();
				}
				catch(InterruptedException e){}
				if(daSvegliare>0 && codaAPriorita.peek().T==Thread.currentThread()){
					daSvegliare--;
					if(daSvegliare>0)
						notifyAll();
					break;
				}
			}
			codaAPriorita.poll();
		}
		else
			permessi=0;
	}

	@Override
	public synchronized void V() {
		// TODO Auto-generated method stub
		if(codaAPriorita.size()==0 || codaAPriorita.size()==daSvegliare)
			permessi = 1;
		else{
			daSvegliare++;
			notifyAll();
		}
	}

}
